package de.busschedule.view;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.database.SQLException;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;

import de.busschedule.R;
import de.busschedule.control.DBHandler;
import de.busschedule.control.GoogleMapHandler;
import de.busschedule.entities.BusLine;
import de.busschedule.logging.Logger;

public class MapActivity extends Activity{
	private final String TAG = "MapActivity";
	private BusLine line;
	private TextView lineVia;
	private DBHandler handler;
	private Resources res;
	
	// Google Map
	private GoogleMap googleMap;
	private final float MAP_ZOOM = 14; // Initial Map Zoom
	private final int MAP_LINE_WIDTH = 18;
	private GoogleMapHandler mapHandler;
	private CheckBox allStops;

	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_linedetail_map);

		Intent intent = getIntent();
		String id = intent.getStringExtra("lineID");
		if(id != null){
			// Open the database
			handler = new DBHandler(this);
			try{
				handler.createDataBase();
			}catch(IOException e){
				Logger.error(TAG, "Could not create database!");
			}
			try{
				handler.openDataBase();
			}catch(SQLException e){
				Logger.error(TAG, "Could not open database!\n" + e.getMessage());
			}
			line = handler.getLine(id);
			if(line != null){
				initUI();
			}
		}
	}

	private void initUI(){
		res = getResources();

		lineVia = (TextView) findViewById(R.id.map_large_line_via);
		lineVia.setText(res.getString(R.string.via) + " " + line.getVia());
		allStops = (android.widget.CheckBox) findViewById(R.id.map_large_check_all_stops);
		
		setActionBar();
	}

	@SuppressLint("DefaultLocale")
	private void setActionBar(){
		//ActionBar
		ActionBar actionBar = getActionBar();
	    actionBar.setDisplayOptions(actionBar.getDisplayOptions()
	            | ActionBar.DISPLAY_SHOW_CUSTOM);	    
	    try{
		    //Get image
		    //filename: [destination][number].png
			Drawable draw = Drawable.createFromStream(getAssets().open("banner/" + line.getFilepath() + ".png"), null);

		    //Set image
		    ImageView imageView = new ImageView(actionBar.getThemedContext());
		    imageView.setScaleType(ImageView.ScaleType.CENTER);
		    imageView.setImageDrawable(draw);
		    
		    ActionBar.LayoutParams layoutParams = new ActionBar.LayoutParams(
		            ActionBar.LayoutParams.WRAP_CONTENT,
		            ActionBar.LayoutParams.WRAP_CONTENT, Gravity.CENTER
		                    | Gravity.CENTER_VERTICAL);
		    layoutParams.leftMargin = 40;
		    imageView.setLayoutParams(layoutParams);
		    actionBar.setCustomView(imageView);
		}catch(IOException e){
			Logger.error(TAG, e.getMessage());
		}
	    
	    actionBar.setIcon(new ColorDrawable(getResources().getColor(android.R.color.transparent))); 
		setTitle("");
	}

	@Override
	public void onResume(){
		initMap();
		super.onResume();
	}

	/**
	 * function to load map. If map is not created it will create it for you
	 * */
	private void initMap(){
		if(googleMap == null){
			googleMap = ((MapFragment) getFragmentManager().findFragmentById(
					R.id.map_large)).getMap();
			// check if map is created successfully or not
			if(googleMap == null){
				Toast.makeText(getApplicationContext(),
						"Sorry! Unable to create maps", Toast.LENGTH_SHORT)
						.show();
				Logger.error(TAG, "Could not create GoogleMap!");
				return;
			}

			// User's position
			googleMap.setMyLocationEnabled(true);
			if(!centerMapOnMyLocation()){
				CameraPosition cameraPosition = new CameraPosition.Builder()
						.target(new LatLng(52.272793, 8.048780)).zoom(MAP_ZOOM)
						.build();
				googleMap.animateCamera(CameraUpdateFactory
						.newCameraPosition(cameraPosition));
			}
			mapHandler = new GoogleMapHandler();

			// Load route from the KML File
			new LoadPath().execute("kml/" + line.getFilepath() + ".kml");
		}
	}

	private boolean centerMapOnMyLocation(){
		// TODO: Test GPS location
		Location location = googleMap.getMyLocation();
		if(location != null){
			// Set camera to position
			CameraPosition cameraPosition = new CameraPosition.Builder()
					.target(new LatLng(location.getLatitude(), location
							.getLongitude())).zoom(MAP_ZOOM).build();
			googleMap.animateCamera(CameraUpdateFactory
					.newCameraPosition(cameraPosition));
			return true;
		}
		return false;
	}

	/**
	 * Fills the Google Map with Route data from a KML file whose filepath is
	 * the first String parameter
	 * 
	 * @author Andre
	 * 
	 */
	private class LoadPath extends AsyncTask<String, Void, Void>{
		Vector<PolylineOptions> path;
		Vector<Vector<LatLng>> path_fragment;
		Vector<Polyline> lines;

		@Override
		protected void onPreExecute(){
			super.onPreExecute();
			path_fragment = new Vector<Vector<LatLng>>();
			path = new Vector<PolylineOptions>();
			lines = new Vector<Polyline>();
		}

		@Override
		protected Void doInBackground(String... params){
			try{
				// Open file from assets folder
				InputStream inputStream = getResources().getAssets().open(
						params[0]);
				DocumentBuilder docBuilder = DocumentBuilderFactory
						.newInstance().newDocumentBuilder();
				Document document = docBuilder.parse(inputStream);
				NodeList listCoordinateTag = null;
				if(document == null){
					return null;
				}

				// Get coordinate tags and parse their contents
				listCoordinateTag = document
						.getElementsByTagName("coordinates");

				for(int i = 0; i < listCoordinateTag.getLength(); i++){
					String coordText = listCoordinateTag.item(i)
							.getFirstChild().getNodeValue().trim();
					String[] vett = coordText.split("\\ ");
					Vector<LatLng> temp = new Vector<LatLng>();
					for(int j = 0; j < vett.length; j++){
						temp.add(new LatLng(Double.parseDouble(vett[j]
								.split("\\,")[1]), Double.parseDouble(vett[j]
								.split("\\,")[0])));
					}
					path_fragment.add(temp);
				}
			}catch(FileNotFoundException e){
				Logger.error(TAG, e.getMessage());
			}catch(ParserConfigurationException e){
				Logger.error(TAG, e.getMessage());
			}catch(SAXException e){
				Logger.error(TAG, e.getMessage());
			}catch(IOException e){
				Logger.error(TAG, e.getMessage());
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result){
			super.onPostExecute(result);
			googleMap.clear();
			setLinePath();
			
			// Add busstop markers for this line to the map
			mapHandler.addMarkers(googleMap, handler, line, false);
			
			allStops.setOnClickListener(new OnClickListener(){
				@Override
				public void onClick(View v){
					Logger.debug(TAG, "clicked ");
					if((((CheckBox) v).isChecked())){
						// Add busstop markers for all lines to the map
						mapHandler.removeMarkers(googleMap);
						mapHandler.addMarkers(googleMap, handler, line, true);
					}else{
						// Add busstop markers for this line to the map
						mapHandler.removeMarkers(googleMap);
						mapHandler.addMarkers(googleMap, handler, line, false);
					}
				}
			});
		}

		private void setLinePath(){// Get lines
			for(int i = 0; i < path_fragment.size(); i++){
				// PolyLine options
				PolylineOptions temp = new PolylineOptions();
				for(int j = 0; j < path_fragment.get(i).size(); j++){
					temp.add(path_fragment.get(i).get(j));
				}
				path.add(temp);
			}

			// Add line
			for(int i = 0; i < path.size(); i++){
				lines.add(googleMap.addPolyline(path.get(i)));
			}

			// Format the lines
			for(int i = 0; i < lines.size(); i++){
				lines.get(i).setWidth(MAP_LINE_WIDTH);
				lines.get(i).setColor(Color.parseColor(line.getColor()));
				lines.get(i).setGeodesic(true);
				lines.get(i).setVisible(true);
			}
			
		}
	}
}
